/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package vigas.calculos.controller;


import java.util.List;
import javax.swing.JOptionPane;
import vigas.calculos.VigaDuploApoio;
import vigas.calculos.VigaDuploEngaste;
import vigas.calculos.VigaEmBalanco;
import vigas.calculos.VigaBalancoExtremidade;
import vigas.componentes.Apoio;
import vigas.componentes.Engaste;
import vigas.componentes.Viga;
import vigas.gui.PainelDeDesenho;
import vigas.gui.VigasApp;
import vigas.util.Constantes;
import vigas.util.MensagemUtil;

/**
 *
 * @author Gabriel
 */
public class VigaCalculosController {

    //vigas
    public VigaDuploApoio vigaDuploApoio;
    public VigaDuploEngaste vigaDuploEngaste;
    public VigaEmBalanco vigaEmBalanço;
    public VigaBalancoExtremidade vigaBalancoExtremidade;

  //  private VigasApp janela; // referência à interface
    //Todas as informações de desenho estão no panel e não no frame
    private PainelDeDesenho janela;

    //numero de pontos dos graficos
    int noPoints;


    double w = 0.; //valor da força/momento concentrado ou do extremo esquerdo da força distribuida
    double w2 = 0.; //valor do extremo direito da força distribuida
    double a = 0.; //distancia da força/momento ao extremo esquerdo da viga

    public double xi[];
    double vi[];
    double mi[];
    double yi[];

    //soma dos valores dos esforços aplicados (resultado do princípio da superposição)
    public double vSum[];
    public double mSum[];
    public double ySum[];

    //momentos e reações resultantes após a adição de cargas
    double rr1sum;
    double rr2sum;
    double mm1sum;
    double mm2sum;

    //somas das cargas adicionadas
    double sumMoment[][] = new double[100][2];
    double sumForce[][] = new double[100][2];     // variable for summing concentrated load
    double sumDist[]; // variable for summing distribulte load

    //contadores
    int momentCount=0;
    int forceCount=0;
    double totalDist =0.;  // total Distribution load added.

    //índices
    int i;
    int j;
    int jj;
    int k;

    float posicaoSegundoApoio=-1;
    float posicaoSegundoEngaste=-1;
    private int numeroApoios, numeroEngastes;
    private static VigaCalculosController vigaCalculosController = null;

    public static VigaCalculosController getInstance(PainelDeDesenho janela){

        if(vigaCalculosController == null){
            vigaCalculosController = new VigaCalculosController(janela);
        }
        return vigaCalculosController;

    }

    public static void resetaController(){
        vigaCalculosController=null;
    }

    // inicializa o controller com a referência à interface
    private VigaCalculosController (PainelDeDesenho janela) {
        this.janela = janela;
        if(janela!=null){
            noPoints = janela.getViga().getQtdDePontos();
            this.vigaDuploApoio = new VigaDuploApoio(28000,2,janela.getViga().comprimentoEmMetros(), noPoints);
            this.vigaEmBalanço = new VigaEmBalanco(28000,2,janela.getViga().comprimentoEmMetros(),noPoints);
            this.vigaBalancoExtremidade = new VigaBalancoExtremidade(28000,2,janela.getViga().comprimentoEmMetros(),noPoints);
            this.vigaDuploEngaste = new VigaDuploEngaste(28000,2,janela.getViga().comprimentoEmMetros(),noPoints);

            xi=new double[noPoints];
            vi=new double[noPoints];
            mi=new double[noPoints];
            yi=new double[noPoints];

            //soma dos valores dos esforços aplicados (resultado do princípio da superposição)
            vSum=new double[noPoints];
            mSum=new double[noPoints];
            ySum=new double[noPoints];

            sumDist = new double[noPoints];
        }

    }

    private void somaEmBalanco(){
        for (i=0;i<noPoints;i++)
            {
                xi[i]=vigaEmBalanço.x[i];
                vi[i]+=vigaEmBalanço.v[i];
                mi[i]+=vigaEmBalanço.m[i];
                yi[i]+=vigaEmBalanço.y[i];
            }
        rr2sum += vigaEmBalanço.rr;
        mm2sum += vigaEmBalanço.mr;

    }

    private void somaDuploApoio(){
        for (i=0;i<noPoints;i++)
            {
                 xi[i]=vigaDuploApoio.x[i];
                vi[i]+=vigaDuploApoio.v[i];
                mi[i]+=vigaDuploApoio.m[i];
                yi[i]+=vigaDuploApoio.y[i];
            }
        rr1sum += vigaDuploApoio.rr1;
        rr2sum += vigaDuploApoio.rr2;


    }

    private void somaDuploEngaste(){
        for (i=0;i<noPoints;i++){
                 xi[i]=vigaDuploEngaste.x[i];
                vi[i]+=vigaDuploEngaste.v[i];
                mi[i]+=vigaDuploEngaste.m[i];
                yi[i]+=vigaDuploEngaste.y[i];
            }
        rr1sum += vigaDuploEngaste.rr1;
        rr2sum += vigaDuploEngaste.rr2;
        mm1sum += vigaDuploEngaste.mm1;
        mm2sum += vigaDuploEngaste.mm2;
    }

    private void somaBalancoExtremidade(){
        for (i=0;i<noPoints;i++)
            {
                xi[i]=vigaBalancoExtremidade.x[i];
                vi[i]+=vigaBalancoExtremidade.v[i];
                mi[i]+=vigaBalancoExtremidade.m[i];
                yi[i]+=vigaBalancoExtremidade.y[i];
            }
        rr1sum += vigaBalancoExtremidade.rr1;
        rr2sum += vigaBalancoExtremidade.rr2;

    }
    public void adicionarCarga () {

        List<Apoio> apoios = janela.getApoios();
        calculaApoios(apoios);

        //viga em balanço
        if (numeroApoios==0 && numeroEngastes==1 && engasteNaExtremidadeEsquerda(apoios, janela.getViga())) {

            if (janela.getCargaAplicada()!=null){
                vigaEmBalanço.calcularEsforcosCargaConcentrada(janela.getCargaAplicada().getValorDaCarga(), janela.getCargaAplicada().getPosicaoRelativa(janela.getViga()));
                somaEmBalanco();
            }
            if (janela.getCargaDistribuida()!=null){
                vigaEmBalanço.calcularEsforcosCargaDistribuida(janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getInicioRelativo(janela.getViga()), janela.getCargaDistribuida().getFimRelativo(janela.getViga()));
                somaEmBalanco();
            }
            if (janela.getMomento()!=null){
                vigaEmBalanço.calcularEsforcosMomentoConcentrado(janela.getMomento().getValorDoMomento(), janela.getMomento().getPosicaoRelativa(janela.getViga()));
                somaEmBalanco();
            }

            preecherResultates(janela.getApoios().get(0), rr2sum, "Ra");
            //preecherResultates(janela.getApoios().get(1), mm2sum, "Mr");
            //somarCargas(tipoCarga);
            somarResultados();
            //...
        }

        //viga com duplo apoio
        else if (numeroApoios == 2 && apoiosEstaoNasExtremidades(apoios, janela.getViga())) {
      //if (true) {
           // vigaDuploApoio = new VigaDuploApoio(janela.vigaElasticidade,janela.vigaMomentoInercia,janela.vigaComprimento,janela.vigaNumeroPontos);

            if (janela.getCargaAplicada()!=null){
                vigaDuploApoio.calcularEsforcosCargaConcentrada(janela.getCargaAplicada().getValorDaCarga(), janela.getCargaAplicada().getPosicaoRelativa(janela.getViga()));
                somaDuploApoio();
            }
            if (janela.getCargaDistribuida() != null){
                vigaDuploApoio.calcularEsforcosCargaDistribuida(janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getInicioRelativo(janela.getViga()), janela.getCargaDistribuida().getFimRelativo(janela.getViga()));
                somaDuploApoio();
            }
            if (janela.getMomento() != null){
                vigaDuploApoio.calcularEsforcosMomentoConcentrado(janela.getMomento().getValorDoMomento(), janela.getMomento().getPosicaoRelativa(janela.getViga()));
                somaDuploApoio();
            }



            preecherResultates(janela.getApoios().get(0), rr1sum, "Ra");
            preecherResultates(janela.getApoios().get(1), rr2sum, "Rb");

            somarResultados();
            //...
        }// fim do if

        else if (numeroApoios == 2 && !apoiosEstaoNasExtremidades(apoios, janela.getViga())) {
      //if (true) {
           // vigaDuploApoio = new VigaDuploApoio(janela.vigaElasticidade,janela.vigaMomentoInercia,janela.vigaComprimento,janela.vigaNumeroPontos);

            vigaBalancoExtremidade.setPosicaoSegundoApoio(posicaoSegundoApoio);

            if (janela.getCargaAplicada()!=null){

                vigaBalancoExtremidade.calcularEsforcosCargaConcentrada(janela.getCargaAplicada().getValorDaCarga(), janela.getCargaAplicada().getPosicaoRelativa(janela.getViga()));
                somaBalancoExtremidade();
            }
            if (janela.getCargaDistribuida() != null) {
                vigaBalancoExtremidade.calcularEsforcosCargaDistribuida(janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getInicioRelativo(janela.getViga()), janela.getCargaDistribuida().getFimRelativo(janela.getViga()));
                somaBalancoExtremidade();
            }
            if (janela.getMomento() != null) {
                vigaBalancoExtremidade.calcularEsforcosMomentoConcentrado(janela.getMomento().getValorDoMomento(), janela.getMomento().getPosicaoRelativa(janela.getViga()));
                somaBalancoExtremidade();
            }



            preecherResultates(janela.getApoios().get(0), rr1sum, "Ra");
            preecherResultates(janela.getApoios().get(1), rr2sum, "Rb");
            somarResultados();
            //...
        }

        //viga duplo engaste
        else if (numeroApoios==0 && numeroEngastes==2 && engastesEstaoNasExtremidades(apoios, janela.getViga())) {
//           // vigaDuploEngaste = new VigaDuploEngaste(janela.vigaElasticidade,janela.vigaMomentoInercia,janela.vigaComprimento,janela.vigaNumeroPontos);
//
            if (janela.getCargaAplicada()!=null){
                vigaDuploEngaste.calcularEsforcosCargaConcentrada(janela.getCargaAplicada().getValorDaCarga(), janela.getCargaAplicada().getPosicaoRelativa(janela.getViga()));
                somaDuploEngaste();
            }
            if (janela.getCargaDistribuida() != null){
                vigaDuploEngaste.calcularEsforcosCargaDistribuida(janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getValorDaCarga(), janela.getCargaDistribuida().getInicioRelativo(janela.getViga()), janela.getCargaDistribuida().getFimRelativo(janela.getViga()));
                somaDuploEngaste();
            }
            if (janela.getMomento() != null){
                vigaDuploEngaste.calcularEsforcosMomentoConcentrado(janela.getMomento().getValorDoMomento(), janela.getMomento().getPosicaoRelativa(janela.getViga()));
                somaDuploEngaste();
            }



            preecherResultates(janela.getApoios().get(0), rr1sum, "Ra");
            preecherResultates(janela.getApoios().get(1), rr2sum, "Rb");

            somarResultados();
            //...
        }

        //não é nenhuma configuração suportada
        else {
            //MensagemUtil.exibirMensagemDeErro(this, "Informe o valor da força em kN");
           // JOptionPane.showMessageDialog(janela, "Configuração da viga não suportada!", "Atenção!", JOptionPane.ERROR_MESSAGE);

        }


//        if (isVigaDuploEngaste()) {
//           // vigaDuploEngaste = new VigaDuploEngaste(janela.vigaElasticidade,janela.vigaMomentoInercia,janela.vigaComprimento,janela.vigaNumeroPontos);
//
//            if (tipoCarga.equals(Constantes.CARGA_CONCENTRADA))
//                vigaDuploEngaste.calcularEsforcosCargaConcentrada(janela.cargaConcentradaForça, janela.cargaConcentradaDistancia);
//           double if (tipoCarga.equals(Constantes.CARGA_DISTRIBUIDA))
//                vigaDuploEngaste.calcularEsforcosCargaDistribuida(janela.cargaDistribuidaForça1, janela.cargaDistribuidaForça2, janela.cargaDistribuidaX1, janela.cargaDistribuidaX2);
//            if (tipoCarga.equals(Constantes.MOMENTO_CONCENTRADO))
//                vigaDuploEngaste.calcularEsforcosMomentoConcentrado(janela.momentoValor, janela.momentoDistancia);
//
//            for (i=0;i<noPoints;i++)
//            {
//                xi[i]=vigaDuploEngaste.x[i];
//                vi[i]+=vigaDuploEngaste.v[i];
//                mi[i]+=vigaDuploEngaste.m[i];
//                yi[i]+=vigaDuploEngaste.y[i];
//            }
//
//            rr1sum += vigaDuploEngaste.rr1;
//            rr2sum += vigaDuploEngaste.rr2;
//            mm1sum += vigaDuploEngaste.mm1;
//            mm2sum += vigaDuploEngaste.mm2;
//
//            somarCargas(tipoCarga);
//            somarResultados();
//            //...
//        }

    }


//    private void somarCargas (String tipoCarga) {
//
//        // soma forças concentradas na mesma posição
//        if (tipoCarga.equals(Constantes.CARGA_CONCENTRADA)) {
//            ++forceCount;
//            sumForce[forceCount][0] = janela.cargaConcentradaForça;
//            sumForce[forceCount][1] = janela.cargaConcentradaDistancia;
//            for (i=1;i<=forceCount-1;i++)
//            {
//                if(a==sumForce[i][1])
//                {
//                    sumForce[i][0]+=janela.cargaConcentradaForça;
//                    --forceCount;
//                    //break;
//                }
//            }
//        }
//
//        //soma forças distribuídas na mesma posição
//        if (tipoCarga.equals(Constantes.CARGA_DISTRIBUIDA)) {
//            totalDist+=janela.cargaDistribuidaForça1*janela.cargaDistribuidaComprimento;
//            //break;
//        }
//
//        //soma momentos concentrados na mesma posição
//        if (tipoCarga.equals(Constantes.MOMENTO_CONCENTRADO)) {
//            momentCount++;
//            sumMoment[momentCount][0] = janela.momentoValor;
//            sumMoment[momentCount][1] = janela.momentoDistancia;
//            for (i=1;i<=momentCount-1;i++)
//            {
//                if(janela.momentoDistancia==sumMoment[i][1])
//                {
//                    sumMoment[i][0]+=janela.momentoValor;
//                    momentCount--;
//                    break;
//                }
//            }
//        }
//
//    }// fim do método somarCargas

    // implementa superposição somando os esforços existentes em todas as posições
    private void somarResultados () {
        for (i=0;i<noPoints;i++)
        {
            // Sum results
            vSum[i]=vSum[i]+vi[i];
            mSum[i]=mSum[i]+mi[i];
            ySum[i]=ySum[i]+yi[i];
        }

    }

    public void reinicializarVetores() {

        for (i=0;i<noPoints;i++)
        {
            // Sum results
            vSum[i]=0;
            mSum[i]=0;
            ySum[i]=0;
        }

    }

    // informa se a viga desenhada é de duplo apoio
    private boolean isVigaDuploApoio() {
        //implementação
        return true;
    }

    // informa se a viga desenhada é de duplo engaste
    private boolean isVigaDuploEngaste() {
        //implementação
        return false;
    }

    // informa se a viga desenhada é em balanço
    private boolean isVigaEmBalanco() {
        //implementação
        return false;
    }

     private boolean apoiosEstaoNasExtremidades(List<Apoio> apoios, Viga v){

            for(Apoio a: apoios)
                if(a.getPontoMarcadoNaviga().x > (v.getInicio()+5) && a.getPontoMarcadoNaviga().x < (v.getFim())-5){
                    posicaoSegundoApoio = ((float)a.getPontoMarcadoNaviga().x - (float)v.getInicio() )/100;
                    return false;
                }
        return true;
    }

     private boolean engastesEstaoNasExtremidades(List<Apoio> apoios, Viga v){

            for(Apoio a: apoios)
                if(a instanceof Engaste){
                    if(a.getPontoMarcadoNaviga().x > (v.getInicio()+2) && a.getPontoMarcadoNaviga().x < (v.getFim())-2){
                        posicaoSegundoEngaste = ((float)a.getPontoMarcadoNaviga().x - (float)v.getInicio() )/100;
                        return false;
                    }
              }
        return true;
    }

     private boolean engasteNaExtremidadeEsquerda(List<Apoio> apoios, Viga v){

            for(Apoio a: apoios)
                if(a instanceof Engaste){
                    if(a.getPontoMarcadoNaviga().x <= (v.getInicio()+5)){
                        return true;
                }
             }
        return false;
    }

     private void calculaApoios(List<Apoio> apoios){

        numeroApoios=0; numeroEngastes=0;

        for(Apoio a: apoios)
            if(a instanceof Engaste)
                numeroEngastes++;
            else
                numeroApoios++;

    }

      public boolean podeGerarGraficos(){
        if (mSum != null && vSum !=null){
            if(mSum.length > 0 && vSum.length > 0)
                return true;
            return false;
        }
            return false;
    }

      private void preecherResultates(Apoio a, double fy, String label){
          a.setResultante(label, 0, (float)fy);
      }
}
